package github.sf.fw.tools.tree.impl;




import github.sf.fw.tools.spi.SpiFactory;
import github.sf.fw.tools.tree.BaseTreeNode;
import github.sf.fw.tools.tree.Node;

import java.util.List;
import java.util.Stack;

public class DefaultTreeBuilder extends BaseTreeBuilder {

    public void setTreeNodeImpl(String treeNodeImpl) {
        this.treeNodeImpl = treeNodeImpl;
    }

    @Override
    public Node buildTree(List<Node> nodes) {
        clearTreeNodeList();
        initialize(nodes);
        BaseTreeNode tempRoot = (BaseTreeNode) createTreeNode();
        List<Node> roots = getRoots();
        Stack<Node> nodeStack = initStackAndAbstractRootNode(tempRoot, roots);
        while (!nodeStack.isEmpty()) {
            BaseTreeNode popNode = (BaseTreeNode) nodeStack.pop();
//            BaseTreeNode.class.isAssignableFrom(popNode.getClass());
            List<Node> childNodes = getIdAndChildNode().get(popNode.obtainNodeId());
            popNode.addPath(popNode.obtainNodeId().toString());
            if (childNodes != null && !childNodes.isEmpty()) {
                for (Node node : childNodes) {
                    //note: node type is BaseNode
                    BaseTreeNode tempTreeNode = configChildNode(popNode, node);
                    popNode.addChildren(tempTreeNode);
                    nodeStack.add(tempTreeNode);
                }
            }
            innerPostHandle(popNode);
        }
        BaseTreeNode.class.isAssignableFrom(tempRoot.getClass());
        if (tempRoot.obtainChildren().size() == 1) {
            this.root = tempRoot.obtainChildren().get(0);
            return this.root;
        }
        //排序
        tempRoot.sortChildren();
        this.root = tempRoot;
        return this.root;
    }

    private BaseTreeNode configChildNode(BaseTreeNode popNode, Node node) {
        BaseTreeNode tempTreeNode = (BaseTreeNode) createTreeNode();
        tempTreeNode.copyFrom(node);
        tempTreeNode.addPathList(popNode.obtainPath());
        return tempTreeNode;
    }

    private void innerPostHandle(BaseTreeNode popNode) {
        //子节点排序
        popNode.sortChildren();
        addNodeToTreeNodeList(popNode);
    }


    /**
     * 初始化用于构建树机构的栈和抽象的根节点
     *
     * @param tempRoot 临时根节点（抽象根节点）
     * @param roots    待构建数据中的根节点
     * @return 栈
     */
    private Stack<Node> initStackAndAbstractRootNode(BaseTreeNode tempRoot, List<Node> roots) {
        Stack<Node> nodeStack = new Stack<>();
        for (Node node : roots) {
            BaseTreeNode treeNode = (BaseTreeNode) createTreeNode();
            treeNode.copyFrom(node);
            tempRoot.addChildren(treeNode);
            nodeStack.add(treeNode);
        }
        return nodeStack;
    }

    @Override
    public List<Node> getChildren(Node node) {
        return null;
    }


    public Node createTreeNode() {
        return SpiFactory.getObject(BaseTreeNode.class, treeNodeImpl);
    }

}
